package com.biscuit.page.basicservice.websocket.chat_room;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.biscuit.page.basicservice.design.websocket.register.ChatRoomWebSocketRegisterContext;
import com.biscuit.page.basicservice.design.websocket.register.WebSocketRegisterTypeEnum;
import com.biscuit.page.basicservice.design.websocket.register.factory.WebSocketRegisterHandlerFactory;
import com.biscuit.page.basicservice.utils.BaseExceptionUtil;
import com.biscuit.page.basicservice.utils.BaseVerifyUtil;
import com.biscuit.page.basicservice.websocket.MessageCallbackTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.Map;
import java.util.Objects;

/**
 * @author biscuit
 * @createTime 2024/6/22 15:55
 */
@Slf4j
@Component
@ServerEndpoint("/websocket/chat/room/{chatRoomId}/{userUid}")
public class ChatRoomWebSocketServer {

    /**
     * 客户端与服务器建立双向通信连接成功后的回调方法
     */
    @OnOpen
    public void connect(Session session,
                        @PathParam("chatRoomId") Long chatRoomId, @PathParam("userUid") String userUid) {
        // 参数校验
        BaseExceptionUtil.throwException(StringUtils.isNotBlank(userUid), "用户Uid为空");
        BaseExceptionUtil.throwException(BaseVerifyUtil.verifyNumberFullValid(chatRoomId), "聊天室Id为空");

        // 提前构建聊天室 WebSocket 连接注册上下文对象
        ChatRoomWebSocketRegisterContext context = new ChatRoomWebSocketRegisterContext();
        context.setChatRoomId(chatRoomId);
        context.setUserUid(userUid);
        context.setSession(session);

        // 获取聊天室 WebSocket 连接注册实现类，并执行注册逻辑
        WebSocketRegisterHandlerFactory.create(WebSocketRegisterTypeEnum.CHAT_ROOM_REGISTER.getType())
                .register(context);
    }

    /**
     * 客户端与服务器双向通信连接断开后的回调方法
     */
    @OnClose
    public void disconnect(Session session) {
        // 根据 sessionId 获取所在聊天室
        String[] sessionMapping = ChatRoomWebSocketHandler.getSessionMapping(session.getId());

        // 根据 sessionId 剔除所维护的对应在线上下文对象
        ChatRoomWebSocketHandler.delContext(session.getId());

        // 向服务器投递刷新在线用户消息
        if (Objects.nonNull(sessionMapping)){
            // 获取会话所在聊天室id 与 在线id
            Long chatRoomId = Long.parseLong(sessionMapping[0]);
            String onlineId = sessionMapping[1];

            // 获取当前聊天室下的所有在新用户上下文对象集合
            Map<String, ChatRoomWebSocketContext> contextMap = ChatRoomWebSocketHandler.getContextMap(chatRoomId);

            // 判空
            if (CollectionUtils.isEmpty(contextMap)) {
                return;
            }

            // 向指定会议室中的在线用户投递消息
            contextMap.keySet().stream().filter(x -> !x.equals(onlineId)).forEach(x -> {
                try {
                    ChatRoomWebSocketContext context = contextMap.get(x);
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("type", MessageCallbackTypeEnum.REFRESH_ONLINE_LIST.getType());
                    context.getSession().getBasicRemote().sendText(jsonObject.toJSONString());
                } catch (Exception e) {
                    log.error("ChatRoomWebSocketServer disconnect error -> {}", e.getMessage());
                }
            });
        }
    }

    /**
     * 收到客户端消息后调用的方法
     */
    @OnMessage
    public void message(String message, Session session) {
        log.info("用户消息:" + message + ",报文:" + message);
    }

    /**
     * 客户端与服务器双向通信连接发生错误时回调方法
     */
    @OnError
    public void error(Session session, Throwable error) {
        log.error(error.getMessage());
    }

}
